Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Add Autocompress Control #122

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

lenary
Copy link
Contributor

@lenary lenary commented Jan 10, 2025

These options allow users better control of when the assembler should turn specific instructions into their smaller equivalents, without having to change the enabled architectures.

A prototype LLVM implementation is available here: llvm/llvm-project#122483

These options allow users better control of when the assembler should
turn specific instructions into their smaller equivalents, without
having to change the enabled architectures.

Signed-off-by: Sam Elliott <[email protected]>
src/asm-manual.adoc Outdated Show resolved Hide resolved
@psherman42
Copy link

Do we really need another option, when there are already existing options and best practices?

.option push
.option norvc
...
.option pop

@lenary
Copy link
Contributor Author

lenary commented Jan 11, 2025

Do we really need another option, when there are already existing options and best practices?

I put more motivation in the LLVM message, for which I apologise, I was writing both messages at the same time. From that motivation:


This will become more useful as the following things happen:

  • .option norvc is deprecated/removed (which is sometimes used for this purpose).
  • Extensions are added where the destination instruction cannot be disabled separately to the source instruction, either because the destination is in the base architecture, or because it is in the same extension as the source.
  • Extensions wider than 32-bits are added, which make CompressPats [the feature used to implement this in LLVM] more complex to use intuitively, especially if the destination is a 32-bit instruction.

This document says the following about .option norvc, which suggests it is not a best practice:

This option will be deprecated soon after .option arch has been widely implemented on main stream open source toolchains.

Another problem with .option (no)rvc is that it is stated to only disable/enable the C extension, and how it interacts with e.g. Zca/Zcf/Zcd is underspecified, not very obvious, and complex.

In short, yes I do think we need an option for controlling this feature.

I'll note that the proposed LLVM implementation correctly works with .option push and .option pop, which is maybe not obvious from the diff.

@jrtc27
Copy link
Contributor

jrtc27 commented Jan 15, 2025

How does this interact with linker relaxation, which can also convert certain uncompressed instructions into compressed equivalents? That is, is this intended to be purely for the assembler, or is it also intended to constrain the linker's relaxations, and if so, how?

@lenary
Copy link
Contributor Author

lenary commented Jan 16, 2025

How does this interact with linker relaxation, which can also convert certain uncompressed instructions into compressed equivalents? That is, is this intended to be purely for the assembler, or is it also intended to constrain the linker's relaxations, and if so, how?

Thanks for bringing this up. I see two main choices:

  • This does nothing for relaxation, it's an assembler-only option.
  • This disables relaxation.

I am tending towards thinking the second is clearer. This option can be explained as "ensure exactly the instructions I wrote are used", which I think means it has to disable relaxation, or else you might still end up with not exactly what you wrote in the final binary.

By this explanation, the option might need to disable the Branch Pseudos as well (which replace a short conditional branch with a short (inverted) conditional branch and a longer jump).

I've covered neither of these options in my prototype so far, but I can update it if we think this is a reasonable direction.

@aswaterman
Copy link
Contributor

This option can be explained as "ensure exactly the instructions I wrote are used"

Don't forget that it cuts the other way, too. The assembler will expand beqz t0, far into bnez t0, 1f; j far; 1:; suppressing that behavior will result in an assembler or linker error. Of course, this behavior isn't compression, it's expansion, and so one could argue it shouldn't be governed by an option named "autocompress".

@lenary
Copy link
Contributor Author

lenary commented Jan 17, 2025

This option can be explained as "ensure exactly the instructions I wrote are used"

Don't forget that it cuts the other way, too. The assembler will expand beqz t0, far into bnez t0, 1f; j far; 1:; suppressing that behavior will result in an assembler or linker error. Of course, this behavior isn't compression, it's expansion, and so one could argue it shouldn't be governed by an option named "autocompress".

That's what I meant by "Branch Pseudos as well (which replace a short conditional branch with a short (inverted) conditional branch and a longer jump)."

In discussion yesterday, it was noted there are other complex pseudos that can emit more than one instruction (call and li for example). I don't see as much of an issue with these other pseudos as they do not share mnemonics with real instructions.

I intend to update the proposal wording in this direction next week.

I didn't hear much dissent about the proposed direction (including the disabling of relaxation and long branch pseudo instructions) in yesterday's RISC-V toolchain SIG and LLVM meetings, but I realise this is still a new proposal.

I wonder if a better name might be (no)replace? It might be too close to (no)relax, but I'm not sure.

I welcome more feedback about this proposal.

@aswaterman
Copy link
Contributor

Off the top of my head, I don’t have a great naming suggestion, but I do think the name should encompass the fact that we’re disabling these branch relaxations, too. “Resize” is the first verb that comes to mind that subsumes “compress” and “expand”, but it’s not especially descriptive.

@lenary
Copy link
Contributor Author

lenary commented Jan 24, 2025

I spent too long thinking about the name since last week.

Right now, we have noautocompress/autocompress, but I'm working on extending the prototype to disable relaxation, and disable the branch pseudos. I think that noresize/resize, and noreplace/replace are too similar to norelax/relax.

Here are some suggestions I'm happier with though, which flip the negative/positive versions:

  • exact/noexact (where noexact is the default), to mean "exactly what is written"
  • fixed/nofixed (where nofixed is the default), to mean "fix the size of what was written"

I'm leaning towards exact/noexact. I think both of these are far enough away from existing options that they won't be confused either.

@aswaterman
Copy link
Contributor

What about noautoresize or similar? If the main goal is to make it look visibly dissimilar to norelax, then the additional "auto" suffices.

@psherman42
Copy link

The problem with exact, fixed, resize, and replace is that they are all relative to something. The use of no on top of auto on top of re makes a triple-negative that is excrutiatingly hard to interpret.
We should be a bit more absolute and concrete. This proposal is about allowing or preventing transformation of instructions from one shape (full 32-bit) style to another shaoe (lesser 16-bit, half) style.
Instead of asymmetric pair of options, one prefixed with with no and the other with no prefix, can we use two self-complementary terms? Something like fullsize and halfsize? We can even be brutally verbose with allow16bitinst and deny16bitinst.
Somthing like this is much more clear, simple, and elegant as Mona Lisa herself.

@lenary
Copy link
Contributor Author

lenary commented Jan 24, 2025

This proposal is about allowing or preventing transformation of instructions from one shape (full 32-bit) style to another shaoe (lesser 16-bit, half) style.

This is not correct. As I said, I'm looking further ahead, to longer-than-32-bit instructions, which some custom extensions are already defining, as well as ensuring that we get exactly one 32-bit conditional branch rather than a conditional branch and a jump.

I do sort-of agree with the layering of "no" and "auto" being fairly confusing, so want to get away from that.

I'm going to proceed with exact/noexact, on the basis that "assemble exactly what was written" is a reasonable name, and isn't, in my opinion, "relative". I think the no prefix matches what we've done for all the other options, even if notexact might be more grammatical.

I don't expect noexact to be used very much, instead people will mostly use .option push; .option exact; ...; .option pop as noexact - the same behaviour as today - will be the default.

@psherman42
Copy link

exact is, in fact, relative. It is relative to what was written.

I still feel much better choices are
fullsize / halfsize allow16bitinst/deny16bitinst`
... or something similar.

I kind of like that unconfusing conjugal pair of verbs allow and deny.

@jrtc27
Copy link
Contributor

jrtc27 commented Jan 24, 2025

allow/deny is out of place with all the existing .option boolean toggles.

fullsize/halfsize/allow16bitinst/deny16bitinst does not encompass the more-than-two instruction sizes that exist once you include 48-bit instructions, as this proposal is trying to do.

(no)exact is the best name I've heard so far, in my opinion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants